import 'dart:convert';

import 'package:dio/dio.dart';
import 'package:connectivity/connectivity.dart';
import 'package:ky_tool_plugin/tools/ky_log_utils.dart';
import 'error_handle.dart';

const int _connectTimeout = 15000; //15s
const int _receiveTimeout = 15000;
const int _sendTimeout = 10000;

typedef Success<T> = Function(T data);
typedef Fail = Function(int code, String msg);
//typedef SuccessListCallback<T> = Function(List<T> data);

class DioUtils {
  // default options


//   static late Dio _dio;
//
//   // 创建 dio 实例对象
//   static Dio createInstance() {
//     LogUtils.d('createInstance=========');
//     if (_dio == null) {
//       LogUtils.d('createInstance=========null');
//       /// 全局属性：请求前缀、连接超时时间、响应超时时间
//       var options = BaseOptions(
//
//         /// 请求的Content-Type，默认值是"application/json; charset=utf-8".
//         /// 如果您想以"application/x-www-form-urlencoded"格式编码请求数据,
//         /// 可以设置此选项为 `Headers.formUrlEncodedContentType`,  这样[Dio]就会自动编码请求体.
// //        contentType: Headers.formUrlEncodedContentType, // 适用于post form表单提交
//         responseType: ResponseType.json,
//         validateStatus: (status) {
//           // 不使用http状态码判断状态，使用AdapterInterceptor来处理（适用于标准REST风格）
//           return true;
//         },
//         baseUrl: '',
//         headers: returnHttpHeaders('capp.com'),
//         connectTimeout: _connectTimeout,
//         receiveTimeout: _receiveTimeout,
//         sendTimeout: _sendTimeout,
//       );
//       _dio = new Dio(options);
//     }
//     return _dio;
//   }


  // 单例模式
  static final DioUtils _instance = DioUtils._internal();
  factory DioUtils() => _instance;
  DioUtils._internal(){
    init();
  }

  late Dio _dio;

  // 初始化请求配置
  init(){
    BaseOptions baseOptions = BaseOptions(

        /// 请求的Content-Type，默认值是"application/json; charset=utf-8".
        /// 如果您想以"application/x-www-form-urlencoded"格式编码请求数据,
        /// 可以设置此选项为 `Headers.formUrlEncodedContentType`,  这样[Dio]就会自动编码请求体.
//        contentType: Headers.formUrlEncodedContentType, // 适用于post form表单提交
        responseType: ResponseType.json,
        validateStatus: (status) {
          // 不使用http状态码判断状态，使用AdapterInterceptor来处理（适用于标准REST风格）
          return true;
        },
        baseUrl: '',
        headers: returnHttpHeaders('capp.com'),
        connectTimeout: _connectTimeout,
        receiveTimeout: _receiveTimeout,
        sendTimeout: _sendTimeout,
      );
    _dio = Dio(baseOptions);
  }

  // 清空 dio 对象
  static clear() {
    // _dio = null;
  }

  // 请求，返回参数为 T
  // method：请求方法，Method.POST等
  // path：请求地址
  // params：请求参数
  // success：请求成功回调
  // error：请求失败回调
  Future request<T>(Method method, String path, dynamic params,
      {required Success success, required Fail fail}) async {
    try {
      //没有网络
      var connectivityResult = await (new Connectivity().checkConnectivity());
      LogUtils.d('beginRequest====$path++++$params');
      if (connectivityResult == ConnectivityResult.none) {
        _onError(ExceptionHandle.net_error, '网络异常，请检查你的网络！', fail);
        LogUtils.d('网络异常，请检查你的网络！');
        return;
      }

      // Dio _dio = createInstance();

      Map paramsMap = Map();
      if (params is Map){
        paramsMap = params;
      }
      Response response;
      if (paramsMap.keys.length == 0) {
        response = await _dio.request(path, options: Options(
            method: MethodValues[method], headers: returnHttpHeaders(path)),);
      } else {

        if (method == Method.POST){
          FormData formData = FormData.fromMap(params);
          response = await _dio.request(path,
              data: formData,
              options: Options(method: MethodValues[method],
                  headers: returnHttpHeaders(path)));
        }else{

          for (int i = 0;i < paramsMap.keys.length; i ++){
            if (i == 0){
              path = '$path?${paramsMap.keys.toList()[i]}=${paramsMap.values.toList()[i]}';
            }else{
              path = '$path&${paramsMap.keys.toList()[i]}=${paramsMap.values.toList()[i]}';
            }

          }
          LogUtils.d('getRequeretPath========$path====${returnHttpHeaders(path)}');
          response = await _dio.request(path, options: Options(
              method: MethodValues[method], headers: returnHttpHeaders(path)),);

        }

      }

//      LogUtils.d('requestUrl====$path+++$params-----$response');
      if (response != null) {
        if (success != null) {
          success(response.data);
        }
      } else {
        _onError(ExceptionHandle.unknown_error, '未知错误', fail);
        LogUtils.d('未知错误');
      }
    } on DioError catch (e) {
      LogUtils.print_('请求出错：' + e.toString());
      final NetError netError = ExceptionHandle.handleException(e);
      _onError(netError.code, netError.msg, fail);
    }
  }
}

Map<String, dynamic> returnHttpHeaders(String path){
  return {
    'Accept': 'application/json,*/*',
    'Content-Type': 'application/json',
  };
}

void _onError(int code, String msg, Fail fail) {
  if (code == null) {
    code = ExceptionHandle.unknown_error;
    msg = '未知异常';
  }
  LogUtils.print_('接口请求异常： code: $code, msg: $msg');
//  KYToast.showError(msg);
  if (fail != null) {
    fail(code, msg);
  }
}

Map<String, dynamic> parseData(String data) {
  return json.decode(data) as Map<String, dynamic>;
}

enum Method { GET, POST, DELETE, PUT, PATCH, HEAD }
//使用：MethodValues[Method.POST]
const MethodValues = {
  Method.GET: "get",
  Method.POST: "post",
  Method.DELETE: "delete",
  Method.PUT: "put",
  Method.PATCH: "patch",
  Method.HEAD: "head",
};
